package com.asas.spaceflight.controller;

import java.util.HashMap;
import java.util.Map;

import com.asas.spaceflight.model.Bullet;
import com.asas.spaceflight.model.Player;
import com.asas.spaceflight.model.World;
import com.asas.spaceflight.model.Player.State;
import com.asas.spaceflight.view.WorldRenderer;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.math.Vector2;

public class PlayerController {
	
	public enum Control {
		THROTTLE_PRESSED, THROTTLE_RELEASED,
		LEFT_PRESSED, LEFT_RELEASED,
		RIGHT_PRESSED, RIGHT_RELEASED,
		FIRE_PRESSED, FIRE_RELEASED
	}
	
	public enum Action {
		THROTTLE, TURN_LEFT, TURN_RIGHT, FIRE, HIT
	}

	private World world;
	private Player player;
	private PhysicalController physicalController;
	private static Map<Action, Boolean> actions = new HashMap<Action, Boolean>();
	private Music throttleSound;
	private Sound fireSound;
	private long lastFireTime;
	static private int FIRE_DELAY = 150;
	
	public PlayerController(World world, PhysicalController physicalController) {		
		this.world = world;
		this.player = this.world.getPlayer();
		this.physicalController = physicalController;
		
		throttleSound = Gdx.audio.newMusic(Gdx.files.internal("data\\throttle.wav"));
		throttleSound.setLooping(false);
		fireSound = Gdx.audio.newSound(Gdx.files.internal("data\\fire.wav"));
		
		actions.put(Action.THROTTLE, false);
		actions.put(Action.TURN_LEFT, false);
		actions.put(Action.TURN_RIGHT, false);
		actions.put(Action.FIRE, false);
		actions.put(Action.HIT, false);
	}
	
	public void start() {
		player.setState(State.IDLE);
		player.getPosition().x = WorldRenderer.WIDTH/2;
		player.getPosition().y = WorldRenderer.HEIGHT/2;
		player.setThrottleAcceleration(12);		// m/s
		player.setMaxSpeed(6);					// m/s
		player.setSpinSpeed(250);				// degrees/s
		player.setAngle(90);					// degrees
		physicalController.getEntities().add(player);	
		
		lastFireTime = 0;
	}
	
	public Player getPlayer() {
		return player;
	}
	
	public void update(float delta) {
		
		// TEMP
		if (player.getState().equals(State.DYING)) {
			throttleSound.pause();
			return;
		}
		
		if (actions.get(Action.TURN_LEFT)) {
			player.setAngle(player.getAngle() + (delta * player.getSpinSpeed()));
		}
		else if (actions.get(Action.TURN_RIGHT)) {
			player.setAngle(player.getAngle() - (delta * player.getSpinSpeed()));
		}

		if (actions.get(Action.THROTTLE)) {
			player.setState(State.THROTTLE);
			
			Vector2 acceleration;
			acceleration = new Vector2(delta * player.getThrottleAcceleration(), 0);
			acceleration.setAngle(player.getAngle());			
			player.getVelocity().add(acceleration);	
			if (player.getVelocity().len() > player.getMaxSpeed()) {
				Util.SetVectorLength(player.getVelocity(), player.getMaxSpeed());
			}
			
			if (!throttleSound.isPlaying()) {
				throttleSound.play();
			}
		}
		else {
			player.setState(State.IDLE);

			if (throttleSound.isPlaying()) {
				throttleSound.pause();
			}			
		}
		
		if (actions.get(Action.FIRE)
				&& System.currentTimeMillis() >= (lastFireTime + FIRE_DELAY)) {
			
			fireSound.play();
			
			float velocity = 7f;
			long lifetime = 1500;
			
			Bullet obj = ObjectFactory.createBullet(player, velocity, lifetime);
			world.getBullets().add(obj);
			physicalController.getEntities().add(obj);
			
			lastFireTime = System.currentTimeMillis();
			actions.put(Action.FIRE, false); // no rapid-fire
		}
	}
	
	public void react(Control control) {
		
		switch (control) {
		
		case THROTTLE_PRESSED: actions.put(Action.THROTTLE, true); break;
		case THROTTLE_RELEASED: actions.put(Action.THROTTLE, false); break;
		
		case LEFT_PRESSED: {
			actions.put(Action.TURN_LEFT, true);
			actions.put(Action.TURN_RIGHT, false);
			break;
		}
		case RIGHT_PRESSED: {
			actions.put(Action.TURN_LEFT, false);
			actions.put(Action.TURN_RIGHT, true);
			break;
		}
		
		case LEFT_RELEASED: actions.put(Action.TURN_LEFT, false); break; 
		case RIGHT_RELEASED: actions.put(Action.TURN_RIGHT, false); break;
		
		case FIRE_PRESSED: actions.put(Action.FIRE, true); break; 
		case FIRE_RELEASED: actions.put(Action.FIRE, false); break;
		}
	}

}
